package cn.edu.neu.softlab633.influencemaximization.sy.M_TLTGreedy;

import cn.edu.neu.softlab633.influencemaximization.sy.bean.CELF.CELFQueue;
import cn.edu.neu.softlab633.influencemaximization.sy.bean.CELF.CELFQueueEle;
import cn.edu.neu.softlab633.influencemaximization.sy.bean.Graph;
import cn.edu.neu.softlab633.influencemaximization.sy.bean.MarginGain;
import cn.edu.neu.softlab633.influencemaximization.sy.bean.Potentiality;
import cn.edu.neu.softlab633.influencemaximization.sy.model.lt.LinearThresholdModel;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;

/**
 * Created by Jason on 2017/5/10.
 */
public class M_TLTGreedy {
    public static int getSeed(double threshold, Double[] query, int k, int p, Graph graph) throws IOException {
//        Graph graph = GraphReader.readGraphFromCSV(g1_filepath, g2_filepath, alignment_filepath);
//        Graph graph = GraphReader.graphReaderTest();
        BufferedWriter bw = new BufferedWriter(new FileWriter("data/result_MTLTGreedy_WZ_" + threshold + "_" + k + "_" + p+".txt"));
        long start = System.currentTimeMillis();
        ArrayList<Potentiality> potentialities = M_Potentiality.calPotentiality(threshold, query, graph);
        CELFQueue celfQueue = M_Candidate.getCandidate(k, p, threshold, query, potentialities, graph);
        ArrayList<Integer> seed = new ArrayList<>();
        MarginGain seed_gain = new MarginGain(0, new HashSet<Integer>());
        int influenceSpread = 0;
        while (seed.size() < k) {
//            if (seed.size() % 10 == 0) {
//                long end = System.currentTimeMillis();
//                System.out.println("MTLTGreedy:    k = " + seed.size());
//                bw.write("MTLTGreedy:    k = " + seed.size());
//                bw.newLine();
//                bw.write("    influence spread: " + influenceSpread);
//                bw.newLine();
//                bw.write("    running time: " + (end - start) + "ms");
//                bw.newLine();
//                System.out.println("    influence spread: " + influenceSpread);
//                System.out.println("    running time: " + (end - start) + "ms");
//            }
            int k_current = seed.size() + 1;
            CELFQueueEle peek_current = celfQueue.peek();
            MarginGain gain_current = peek_current.getGain();
            while (peek_current.getRound() != k_current) {
                // 更新增益，添加到celf队列
//                seed_gain.getMarginGainNode().add(peek_current.getId());
                MarginGain tmp = LinearThresholdModel.influencePropagation(threshold, query, getCurrentSeed(seed, peek_current.getId()), graph);
//                seed_gain.getMarginGainNode().remove(peek_current.getId());
                gain_current = tmp.sub(seed_gain);
                CELFQueueEle ele = new CELFQueueEle(peek_current.getId(), gain_current, k_current);
                celfQueue.add(ele);
                peek_current = celfQueue.peek();
            }
            if (peek_current.getGain().getMarginGainNum() <= 0) {
                break;
            }
            seed.add(peek_current.getId());
            seed_gain = seed_gain.add(peek_current.getGain());
            influenceSpread += peek_current.getGain().getMarginGainNum();
//            M_Candidate_Update.candidateUpdate(k, p, celfQueue, potentialities, peek_current.getGain(), graph);
        }
        long end = System.currentTimeMillis();
        System.out.println("MTLTGreedy:    k = " + k + "    p = " + p);
        bw.write("MTLTGreedy:    k = " + k + "  p = " + p);
        bw.newLine();
        bw.write("    influence spread: " + influenceSpread);
        bw.newLine();
        bw.write("    running time: " + (end - start) + "ms");
        bw.newLine();
        System.out.println("    influence spread: " + influenceSpread);
        System.out.println("    running time: " + (end - start) + "ms");
        System.out.println("    yinxiangli :" + influenceSpread);
//        System.out.print("  zhongziji :  ");
//        for (int i = 0; i < seed.size(); i++) {
//            Integer integer = seed.get(i);
//            System.out.print(integer + "  ");
//        }
        bw.close();
        return influenceSpread;
    }

    public static ArrayList<Integer> getCurrentSeed(Collection<Integer> seed, int currentSeed) {
        ArrayList<Integer> tmp = new ArrayList<>();
        for (Iterator<Integer> iterator = seed.iterator(); iterator.hasNext(); ) {
            Integer next = iterator.next();
            tmp.add(next);
        }
        tmp.add(currentSeed);
        return tmp;
    }
}